<?php
// 装饰器模式decorator

/**
 * 使用场景：当某一功能或方法draw，要满足不同的功能需求时，可以使用装饰器模式；实现方式：在方法的类中建addDecorator(添加装饰器),beforeDraw,afterDraw 3个新方法， 后2个分别放置在要修改的方法draw首尾.然后创建不同的装器类（其中要包含相同的,beforeDraw,afterDraw方法）能过addDecorator添加进去，然后在beforeDraw,afterDraw中循环处理，与观察者模式使用有点相似
1.装饰器模式（Decorator），可以动态地添加修改类的功能
2.一个类提供了一项功能，如果要在修改并添加额外的功能，传统的编程模式，需要写一个子类继承它，并重新实现类的方法
3.使用装饰器模式，仅需在运行时添加一个装饰器对象即可实现，可以实现最大的灵活性
*/
interface DrawDecorator{
    function beforeDraw();
    function afterDraw();
}
class Canvas{
    public $data;
    protected $decorators = array();

    //Decorator
    function init($width = 20, $height = 10)
    {
        $data = array();
        for($i = 0; $i < $height; $i++)
        {
            for($j = 0; $j < $width; $j++)
            {
                $data[$i][$j] = '*';
            }
        }
        $this->data = $data;
    }

    function addDecorator(DrawDecorator $decorator)
    {
        $this->decorators[] = $decorator;
    }

    function beforeDraw()
    {
        foreach($this->decorators as $decorator)
        {
            $decorator->beforeDraw();
        }
    }

    function afterDraw()
    {
        $decorators = array_reverse($this->decorators);
        foreach($decorators as $decorator)
        {
            $decorator->afterDraw();
        }
    }

    function draw()
    {
        $this->beforeDraw();
        foreach($this->data as $line)
        {
            foreach($line as $char)
            {
                echo $char;
            }
            echo "<br />\n";
        }
        $this->afterDraw();
    }

    function rect($a1, $a2, $b1, $b2)
    {
        foreach($this->data as $k1 => $line)
        {
            if ($k1 < $a1 or $k1 > $a2) continue;
            foreach($line as $k2 => $char)
            {
                if ($k2 < $b1 or $k2 > $b2) continue;
                $this->data[$k1][$k2] = ' ';
            }
        }
    }
}

class ColorDrawDecorator implements DrawDecorator
{
    protected $color;
    function __construct($color = 'red')
    {
        $this->color = $color;
    }
    function beforeDraw()
    {
        echo "<div style='color: {$this->color};'>";
    }
    function afterDraw()
    {
        echo "</div>";
    }
}

$canvas = new Canvas();
$canvas->init();
$canvas->addDecorator(new ColorDrawDecorator('green'));
$canvas->rect(3,6,4,12);
$canvas->draw();





interface Component {
    public function operation();
}


abstract class Decorator implements Component{
    protected $Component;
    public function __construct(Component $component){
        $this->Component =$component;
    }

    public function operation()
    {
        // TODO: Implement operation() method.
        $this->Component->operation();
    }
}

class ConcreteDecoratorA extends Decorator{
    public function __construct(Component $component)
    {
        parent::__construct($component);
    }
    public function operation()
    {
        parent::operation();//  调用装饰类的操作 // TODO: Change the autogenerated stub
        $this->addedOperationA();
    }
    public function addedOperationA(){
        echo 'addedOperationA';
    }
}
class ConcreteDecoratorB extends Decorator { // 具体装饰类B
    public function __construct(Component $component) {
        parent::__construct($component);
    }
    public function operation() {
        parent::operation();
        $this->addedOperationB();
    }
    public function addedOperationB() {echo "B加点辣椒;";}
}
class ConcreteComponent implements Component{ //具体组件类
    public function operation() {}
}

// clients
$component = new ConcreteComponent();
$decoratorA = new ConcreteDecoratorA($component);
$decoratorB = new ConcreteDecoratorB($decoratorA);

$decoratorA->operation();
echo '<br>--------<br>';
$decoratorB->operation();


